import { DataTableColumn, TreeSelectOption } from 'naive-ui'
import { TablePropsType } from '@/types/components'
import {
  addDays,
  addMonths,
  addYears,
  startOfMonth,
  endOfMonth,
  startOfDay,
  endOfDay,
  startOfWeek,
  startOfYear,
  endOfYear,
} from "date-fns/esm";
import moment from "moment-timezone";

export const covertTime2TimeZoneStr = (time:number, timezone:string)=>{
  const localTime  = moment.tz(timestampToDateTime(time), moment.tz.guess(true));
  // console.log(localTime,"+++++++++++++++++1")
  const losAngeles = localTime.clone().tz(timezone);
  // console.log(losAngeles,"+++++++++++++++++2")
  return losAngeles.format('YYYY-MM-DD HH:mm:ss')
}
export const convertEvent = (events:any, timezone:string)=>{
  if(events && timezone) return (events as Array<any>).map(e=>{
    if(e.date) e.date = covertTime2TimeZoneStr(e.date,timezone)
    if(e.start) e.start = covertTime2TimeZoneStr(e.start,timezone)
    if(e.end) e.end = covertTime2TimeZoneStr(e.end,timezone)
    return e;
  })
  return events;
}

export function generateUUID(): string {
  let d = new Date().getTime(); // 生成时间戳
  const uuid = "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, function (c) {
    const r = (d + Math.random() * 16) % 16 | 0;
    d = Math.floor(d / 16);
    return (c === "x" ? r : (r & 0x3) | 0x8).toString(16);
  });
  return uuid;
}
/**
 * 指定日期增加n月
 * @param dateStr 指定日期
 * @param num 月
 * @param type 0:2023-01-30   1：2022-01-30 11:11:11
 * @returns {string}
 * @author: Leo
 */
export function commonAddMouth(dateStr: string | number, num: number | string, type: number | string) {
  let monthNum = 0;
  if (typeof num == "string") {
    monthNum = parseInt(num);
  } else {
    monthNum = num;
  }
  const date = new Date(dateStr);
  //获取原日
  let day: number | string = date.getDate();
  //获取原月份
  // let month = date.getMonth();
  //设置增加月份
  date.setMonth(date.getMonth() + monthNum * 1, 1);
  //获取增加的后的月份
  let Jmonth: number | string = date.getMonth() + 1;
  //获取增加的后的年份
  const Jyear: number | string = date.getFullYear();
  if (Jmonth == 4 || Jmonth == 6 || Jmonth == 9 || Jmonth == 11) {
    //小月
    if (day > 30) {
      day = 30;
    }
  } else if (Jmonth == 2) {
    //2月判断是否闰年
    if ((Jyear % 4 == 0 && Jyear % 100 != 0) || Jyear % 400 == 0) {
      if (day > 29) {
        day = 29;
      }
    }
    if (day > 28) {
      day = 28;
    }
  } else {
    //大月
    if (day > 31) {
      day = 31;
    }
  }
  let tHours: number | string = date.getHours();
  let tMinutes: number | string = date.getMinutes();
  let tSeconds: number | string = date.getSeconds();
  tHours = tHours < 10 ? "0" + tHours : tHours;
  tMinutes = tMinutes < 10 ? "0" + tMinutes : tMinutes;
  tSeconds = tSeconds < 10 ? "0" + tSeconds : tSeconds;
  Jmonth = doHandleMonth(Jmonth);
  day = doHandleMonth(day);
  if (type == "0") {
    return `${Jyear}-${Jmonth}-${day}`;
  }

  return `${Jyear}-${Jmonth}-${day} ${tHours}:${tMinutes}:${tSeconds}`;
}
/**
 *  日或月补0
 * @param month
 * @returns {string}
 */
function doHandleMonth(month: number | string) {
  let m = month;
  if (month.toString().length == 1) {
    m = "0" + month;
  }
  return m;
}
export function getXmonthToday2Stamp(type: number, timeStamp: number) {
  if (timeStamp === 0 || timeStamp === undefined || type === undefined) return 0;
  const str = commonAddMouth(timeStamp, type, 1);
  return new Date(str).getTime();
}

export function beforeDDL(deadLine: number | undefined | null, beforeDDL2Mention: number, mentionUnit: number): number {
  if (
      deadLine === undefined ||
      deadLine === null ||
      deadLine === 0 ||
      beforeDDL2Mention === undefined ||
      isNaN(beforeDDL2Mention) ||
      mentionUnit === undefined
  )
    return 0;
  // if (mentionUnit === 1) return deadLine + beforeDDL2Mention * 1000 * 60 * 60 * 24;
  // if (mentionUnit === 2) return getXmonthToday2Stamp(beforeDDL2Mention, deadLine);
  // if (mentionUnit === 3) return getXmonthToday2Stamp(12 * beforeDDL2Mention, deadLine);
  // console.log(deadLine,beforeDDL2Mention,mentionUnit)
  if (mentionUnit === 1) return addDays(deadLine, beforeDDL2Mention).valueOf();
  if (mentionUnit === 2) return addMonths(deadLine, beforeDDL2Mention).valueOf();
  if (mentionUnit === 3) return addYears(deadLine, beforeDDL2Mention).valueOf();
  if (mentionUnit === 4) return addDays(deadLine, beforeDDL2Mention*7).valueOf();
  return 0;
}

export function computeRangeMonth(start: number, end: number) {
  const monthRangeTimeStamp = [];
  monthRangeTimeStamp.push(start);
  start = addMonths(start, 1).valueOf();
  while (start <= end) {
    monthRangeTimeStamp.push(start);
    start = addMonths(start, 1).valueOf();
  }
  return monthRangeTimeStamp;
}

export function getstartOfDay(date: number) {
  return startOfDay(date).valueOf();
}
export function getEndOfDay(date: number) {
  return endOfDay(date).valueOf();
}
export function getWeek(timeStamp: number) {
  // const endDate = endOfWeek(timeStamp,{weekStartsOn:1})
  const startDate = startOfWeek(timeStamp, { weekStartsOn: 1 }).valueOf();
  const result = new Array<number>();
  for (let i = 0; i < 7; i++) {
    result.push(addDays(startDate, i).getTime());
  }
  return result;
}
export function getMonth(timeStamp: number) {
  // const endDate = endOfWeek(timeStamp,{weekStartsOn:1})
  let startDate = startOfMonth(timeStamp).valueOf();
  const endDate = endOfMonth(timeStamp).valueOf();
  const result = new Array<number>();
  for (let i = startDate; startDate <= endDate; i++) {
    result.push(startDate);
    startDate = addDays(startDate, 1).getTime();
  }
  return result;
}
export function getYear(timeStamp: number) {
  // const endDate = endOfWeek(timeStamp,{weekStartsOn:1})
  let startDate = startOfYear(timeStamp).valueOf();
  const endDate = endOfYear(timeStamp).valueOf();
  const result = new Array<number>();
  for (let i = startDate; startDate <= endDate; i++) {
    result.push(startDate);
    startDate = addMonths(startDate, 1).getTime();
  }
  return result;
}

export function changeTimeUnit(timeStamp: number|undefined|string|null): string {
  if(timeStamp===null || timeStamp===undefined || timeStamp===0) return "0分钟"
  //1、通过“Math.trunc()”方法去除数字的小数部分，保留整数部分；2、通过“Math.round()”方法返回一个数字四舍五入后的整数部分；3、通过“Math.ceil()”方法实现向上取整等等。
  // console.log(timeStamp);
  // type:1变成分钟
  let min = Math.trunc(parseInt(timeStamp.toString()) / (60 * 1000));
  let hour = Math.trunc(min / 60);
  min = min - hour * 60;
  let day = Math.trunc(hour / 24);
  hour = hour - day * 24;
  let month = Math.trunc(day / 30);
  day = day - month * 30;
  const year = Math.trunc(month / 12);
  month = month - year * 12;
  return (
      (year === 0 ? "" : year + "年") +
      (month === 0 ? "" : month + "月") +
      (day === 0 ? "" : day + "天") +
      (hour === 0 ? "" : hour + "小时") +
      (min === 0 ? "" : min + "分钟")
  );
}

export function timeToTimestamp(timeStr: string): number {
  const date = new Date(timeStr);
  // 有三种方式获取
  const time1 = date.getTime();
  // var time2 = date.valueOf();
  // var time3 = Date.parse(date);
  // console.log(time1); //1670145353555
  // console.log(time2); //1670145353555
  // console.log(time3); //1670145353000
  return time1;
}

export function timestampToTime(timestamp: number): string {
  if (timestamp === undefined || timestamp === 0) return "";
  // 时间戳为10位需*1000，时间戳为13位不需乘1000
  const date = new Date(timestamp);
  // const Y = date.getFullYear() + "-";
  // const M = (date.getMonth() + 1 < 10 ? "0" + (date.getMonth() + 1) : date.getMonth() + 1) + "-";
  // const D = (date.getDate() < 10 ? "0" + date.getDate() : date.getDate()) + " ";
  const h = (date.getHours() < 10 ? "0" + date.getHours() : date.getHours()) + ":";
  const m = (date.getMinutes() < 10 ? "0" + date.getMinutes() : date.getMinutes()) + ":";
  const s = date.getSeconds() < 10 ? "0" + date.getSeconds() : date.getSeconds();
  return h + m + s;
}

export function timestampToDateTime(timestamp: number | undefined | null): string {
  if (timestamp === 0 || timestamp === undefined || timestamp === null) return "";
  // 时间戳为10位需*1000，时间戳为13位不需乘1000
  const date = new Date(timestamp);
  const Y = date.getFullYear() + "-";
  const M = (date.getMonth() + 1 < 10 ? "0" + (date.getMonth() + 1) : date.getMonth() + 1) + "-";
  const D = (date.getDate() < 10 ? "0" + date.getDate() : date.getDate()) + " ";
  const h = (date.getHours() < 10 ? "0" + date.getHours() : date.getHours()) + ":";
  const m = (date.getMinutes() < 10 ? "0" + date.getMinutes() : date.getMinutes()) + ":";
  const s = date.getSeconds() < 10 ? "0" + date.getSeconds() : date.getSeconds();
  return Y + M + D + h + m + s;
}
export function isExternal(path: string) {
  return /^(https?:|mailto:|tel:)/.test(path)
}

export function uuid() {
  const s: Array<any> = []
  const hexDigits = '0123456789abcdef'
  for (let i = 0; i < 36; i++) {
    s[i] = hexDigits.substr(Math.floor(Math.random() * 0x10), 1)
  }
  s[14] = '4' // bits 12-15 of the time_hi_and_version field to 0010
  s[19] = hexDigits.substr((s[19] & 0x3) | 0x8, 1) // bits 6-7 of the clock_seq_hi_and_reserved to 01
  s[8] = s[13] = s[18] = s[23] = '-'
  const uuid = s.join('')
  return uuid
}

export function randomString(length: number) {
  const str = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
  let result = ''
  for (let i = length; i > 0; --i) {
    result += str[Math.floor(Math.random() * str.length)]
  }
  return result
}

/**
 * 中划线字符驼峰
 * @param {*} str 要转换的字符串
 * @returns 返回值
 */
export function toHump(str: string): string {
  if (!str) return str
  return str
    .replace(/\-(\w)/g, function (all, letter) {
      return letter.toUpperCase()
    })
    .replace(/(\s|^)[a-z]/g, function (char) {
      return char.toUpperCase()
    })
}

export function sortColumns(originColumns: DataTableColumn[], newColumns: TablePropsType[]) {
  if (!originColumns || !newColumns) {
    return
  }
  if (newColumns.length === 0) {
    originColumns.length = 0
  } else {
    const selectionItem = originColumns.find((it) => it.type === 'selection')
    originColumns.length = 0
    if (selectionItem) {
      originColumns.push(selectionItem)
    }
    originColumns.push(...newColumns)
  }
}

export function transformTreeSelect(
  origin: any[],
  labelName: string,
  keyName: string
): TreeSelectOption[] {
  const tempSelections: TreeSelectOption[] = []
  origin.forEach((it) => {
    const selection = {
      label: it[labelName],
      key: it[keyName],
    } as TreeSelectOption
    if (it.children) {
      selection.children = transformTreeSelect(it.children, labelName, keyName)
    }
    tempSelections.push(selection)
  })
  return tempSelections
}

/**
 * 处理map类型序列化后为 {} 的情况
 */
export function stringify(obj: any): string {
  return JSON.stringify(cloneToObject(obj));
}
export function obj2Map(obj:any):Map<string,any>{
  return new Map(Object.entries(obj))
}
// 将字段包含map的对象转为json对象的格式
export function cloneToObject(obj: any): any {
  let newObj: any = obj;
  if (obj instanceof Map) {
    return Object.fromEntries(obj);
  }
  if (obj instanceof Object) {
    newObj = {};
    const keys = Object.keys(obj);
    const values = Object.values(obj);
    for (let i = 0; i < keys.length; i++) {
      const key = keys[i];
      const value = values[i];
      newObj[key] = cloneToObject(value);
    }
  }
  if (obj instanceof Array) {
    newObj = [];
    for (let i = 0; i < obj.length; i++) {
      newObj[i] = cloneToObject(obj[i]);
    }
  }
  return newObj;
}
